﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Reflection;
using BobcatUtility;

namespace CNStreaming
{
    /// <summary>
    /// Contains mostly static functions to help serialize objects which support 
    /// the IStreamable interface to streams or byte arrays.
    /// 
    /// toByteArray, fromByteArray
    /// --------------------------
    /// These methods take an object that supports the IStreamable interface and
    /// converts them to a byte array, which can be stored in a DB BLOB, or sent
    /// as a network message.
    /// </summary>
    public class StreamHelper
    {
        #region Public methods

        /// <summary>
        /// Converts the streamable object into a byte array.
        /// </summary>
        public static byte[] convertToByteArray(IStreamable streamable)
        {
            MessageStream stream = new MessageStream();

            // We add the version...
            stream.writeInt(streamable.getMessageVersion());

            // We add the type info, so that we can create an object at the point
            // where we receive or load the stream...
            Type type = streamable.GetType();
            stream.writeString(type.AssemblyQualifiedName);

            // We write the data from the object itself...
            streamable.toStream(stream);

            // We convert the message to a byte array, and close the stream...
            byte[] byteArray = stream.toByteArray();
            stream.Close();

            return byteArray;
        }

        /// <summary>
        /// Converts the byte array into an object of the templated type.
        /// (This assumes that the byte array was created from a streamable
        /// object initially.)
        /// </summary>
        public static T convertFromByteArray<T>(byte[] byteArray)
        {
            MessageStream stream = new MessageStream(byteArray);

            // We get the version...
            int iVersion = stream.readInt();

            // We get the object type, and create an instance of it using reflection
            // on the name of the type...
            string strType = stream.readString();
            Type type = Type.GetType(strType);
            IStreamable streamable = (IStreamable)Activator.CreateInstance(type);

            try
            {
                // We deserialize the object from the data in the stream...
                streamable.fromStream(stream, iVersion);
            }
            catch (Exception ex)
            {
                Logger.log(ex.Message, Logger.Level.WARN);
            }

            return (T)streamable;
        }

        #endregion

    }
}
